package com.hrm.system;

import com.hrm.common.shiro.realm.hrmRealm;
import com.hrm.common.shiro.session.CustomSessionManager;
import com.hrm.system.shiro.realm.UserRealm;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @Author: 林海湾Sea
 * @Date :  2021/12/28 10:58
 * @Decription: shiro的配置类
 */
@Configuration
public class ShiroConfiguration {

    // 1、创建realm
    @Bean
    public hrmRealm getRelam() {
        return new UserRealm();
    }

    // 2、创建安全管理器
    @Bean
    public SecurityManager getSecurityManager(hrmRealm realm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(realm);

        // 将自定义的会话管理器注册到安全管理器中
        securityManager.setSessionManager(sessionManager());
        // 将自定义的redis缓存管理器注册到安全管理器中
        securityManager.setCacheManager(cacheManager());

        return securityManager;
    }

    /**
     * 配置Shiro的过滤器工厂，
     * 在web程序中，Shiro进行权限控制，是通过一组过滤器集合进行控制
     * @param securityManager
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {

        // 1、创建过滤器工厂
        ShiroFilterFactoryBean filterFactory = new ShiroFilterFactoryBean();
        // 2、设置安全管理器
        filterFactory.setSecurityManager(securityManager);
        // 3、通用配置（跳转登录页面、未授权跳转的页面）
        filterFactory.setLoginUrl("/autherror?code=1");
        filterFactory.setUnauthorizedUrl("/autherror?code=2");
        /**
         * 4、设置过滤器集合
         * key: 访问链接（支持通配符的形式）
         * value：过滤器类型
         *        Shiro常用过滤器
         *          anno： 匿名访问（表明此链接所有人可以访问）
         *          authc：认证后访问（表明此链接需要登录认证成功之后可以访问）
         */
        Map<String,String> filterMap = new LinkedHashMap<>();
        // anon--匿名访问（所有人可以使用）
        filterMap.put("/sys/login", "anon");
        filterMap.put("/sys/city/**","anon");
        filterMap.put("/sys/faceLogin/**","anon");
        filterMap.put("/autherror","anon");

        // 认证之后访问（登录）
        filterMap.put("/**","authc");
        // perms--具有某种权限（使用注解配置授权）--设置过滤器
        filterFactory.setFilterChainDefinitionMap(filterMap);

        return filterFactory;
    }

    /**
     * 配置相关redis信息
     */
    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.port}")
    private int port;

    /**
     * 1、redis的控制器，操作redis
     */
    public RedisManager redisManager() {
        RedisManager redisManager = new RedisManager();
        redisManager.setHost(host);
        redisManager.setPort(port);
        return redisManager;
    }

    /**
     * 2、sessionDao
     */
    public RedisSessionDAO redisSessionDAO() {
        RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
        redisSessionDAO.setRedisManager(redisManager());
        return redisSessionDAO;
    }

    /**
     * 3、会话管理器
     * @return
     */
    public CustomSessionManager sessionManager() {
        CustomSessionManager sessionManager = new CustomSessionManager();
        sessionManager.setSessionDAO(redisSessionDAO());
        //禁用cookie
        //sessionManager.setSessionIdCookieEnabled(false);
        //禁用url重写   url;jsessionid=id
        sessionManager.setSessionIdUrlRewritingEnabled(false);
        return sessionManager;
    }

    /**
     * 4、缓存管理器
     */
    public RedisCacheManager cacheManager() {
        RedisCacheManager redisCacheManager = new RedisCacheManager();
        redisCacheManager.setRedisManager(redisManager());
        return redisCacheManager;
    }

    //开启对shiro注解的支持
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }
}
